<!doctype html>
<html lang="zh-CN">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>智慧历史 - 校园历史文化数字地图</title>
  <style>
    :root {
      --primary-color: #2c3e50;
      --secondary-color: #3498db;
      --accent-color: #2ecc71;
      --danger-color: #e74c3c;
      --light-bg: #f8f9fa;
      --light-border: #e9ecef;
      --text-primary: #2c3e50;
      --text-secondary: #6c757d;
      --shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
      --shadow-hover: 0 6px 16px rgba(0, 0, 0, 0.15);
    }
    
    body, html {
      margin: 0;
      padding: 0;
      width: 100%;
      height: 100%;
      font-family: "Segoe UI", "Microsoft YaHei", sans-serif;
      overflow: hidden;
      background-color: #f5f7fa;
      color: var(--text-primary);
    }

    /* 顶部导航栏 */
    header {
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 60px;
      background: linear-gradient(135deg, var(--primary-color), #34495e);
      color: #fff;
      display: flex;
      align-items: center;
      gap: 15px;
      padding: 0 20px;
      box-sizing: border-box;
      z-index: 1200;
      box-shadow: var(--shadow);
    }
    
    header h1 { 
      margin: 0; 
      font-size: 20px; 
      flex-shrink: 0; 
      color: #fff;
      font-weight: 500;
      letter-spacing: 0.5px;
    }

    /* 左侧搜索 */
    #searchBox { 
      display: flex; 
      align-items: center; 
      gap: 8px; 
      margin-left: 15px;
      position: relative;
    }
    
    #searchInput {
      height: 36px; 
      width: 280px; 
      padding: 8px 15px; 
      border-radius: 20px;
      border: none; 
      outline: none; 
      font-size: 14px;
      background-color: rgba(255, 255, 255, 0.9);
      transition: all 0.3s ease;
      box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1);
    }
    
    #searchInput:focus {
      background-color: #fff;
      box-shadow: 0 0 0 2px rgba(52, 152, 219, 0.3);
    }
    
    #searchBtn {
      height: 36px; 
      width: 36px;
      padding: 0; 
      border-radius: 50%; 
      border: none;
      background: var(--secondary-color); 
      color: white; 
      cursor: pointer; 
      font-size: 16px;
      display: flex;
      align-items: center;
      justify-content: center;
      transition: all 0.3s ease;
      box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
    }
    
    #searchBtn:hover { 
      background:#2980b9;
      transform: translateY(-2px);
      box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
    }

    /* 中间：按钮组 */
    .center-group { 
      display:flex; 
      align-items:center; 
      gap:10px; 
      margin-left: 15px;
    }
    
    .btn { 
      background:var(--accent-color); 
      color:#fff; 
      border:none; 
      padding:8px 16px; 
      border-radius:20px; 
      cursor:pointer; 
      font-size:14px;
      font-weight: 500;
      transition: all 0.3s ease;
      box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
    }
    
    .btn.secondary { 
      background:var(--secondary-color);
    }
    
    .btn:hover { 
      opacity:0.9;
      transform: translateY(-2px);
      box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
    }

    /* 下拉（通过 .open 控制显示，不用 :hover） */
    .dropdown { 
      position: relative; 
      display:inline-block;
    }
    
    .dropdown .drop-toggle { 
      background: var(--secondary-color); 
      color: white; 
      border-radius: 20px; 
      padding: 8px 16px; 
      border: none; 
      cursor: pointer;
      font-weight: 500;
      transition: all 0.3s ease;
      box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
      display: flex;
      align-items: center;
    }
    
    .dropdown .drop-toggle:hover {
      opacity: 0.9;
      transform: translateY(-2px);
      box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
    }
    
    .dropdown .dropdown-content {
      display: none;
      position: absolute;
      top: calc(100% + 8px);
      left: 0;
      background:#fff; 
      color:#333;
      min-width:240px; 
      border-radius:8px; 
      box-shadow:var(--shadow-hover);
      z-index:1300; 
      overflow:hidden;
      animation: fadeInDown 0.3s ease;
    }
    
    @keyframes fadeInDown {
      from {
        opacity: 0;
        transform: translateY(-10px);
      }
      to {
        opacity: 1;
        transform: translateY(0);
      }
    }
    
    .dropdown.open .dropdown-content { 
      display:block; 
    }
    
    .dropdown .dropdown-content button {
      display:block; 
      width:100%; 
      text-align:left; 
      padding:12px 16px; 
      border:none; 
      background:none; 
      cursor:pointer; 
      font-size:14px;
      transition: all 0.2s ease;
      border-bottom: 1px solid var(--light-border);
    }
    
    .dropdown .dropdown-content button:last-child {
      border-bottom: none;
    }
    
    .dropdown .dropdown-content button:hover { 
      background:var(--light-bg);
      padding-left: 20px;
    }

    /* 右侧地标面板 */
    #landmarkPanel {
      position:absolute; 
      top:70px; 
      right:0; 
      width:320px; 
      height: calc(100% - 70px);
      background: rgba(255,255,255,0.98); 
      box-shadow: -4px 0 15px rgba(0,0,0,0.1);
      padding: 20px; 
      overflow:auto; 
      z-index:1100; 
      display:none;
      border-top-left-radius: 12px;
      animation: slideInRight 0.4s ease;
    }
    
    @keyframes slideInRight {
      from {
        transform: translateX(100%);
      }
      to {
        transform: translateX(0);
      }
    }
    
    #landmarkPanel h3 { 
      margin:0 0 15px 0; 
      font-size:18px; 
      color:var(--primary-color);
      font-weight: 500;
      padding-bottom: 10px;
      border-bottom: 2px solid var(--light-border);
    }
    
    .landmark-item { 
      padding:15px; 
      border-radius:8px;
      margin-bottom: 10px;
      cursor:pointer;
      transition: all 0.3s ease;
      border: 1px solid var(--light-border);
      background-color: #fff;
    }
    
    .landmark-item:hover { 
      background:var(--light-bg);
      transform: translateY(-2px);
      box-shadow: var(--shadow);
    }
    
    .landmark-item strong {
      color: var(--primary-color);
      font-size: 16px;
      display: block;
      margin-bottom: 6px;
    }

    /* 时间轴 - 左下角 */
    #timeControls {
      position:absolute; 
      bottom:20px; 
      left:20px; 
      z-index:1050;
      background: rgba(255,255,255,0.95); 
      padding:15px; 
      border-radius:12px;
      display:flex; 
      align-items:center; 
      gap:12px; 
      box-shadow:var(--shadow-hover);
      border: 1px solid var(--light-border);
    }
    
    #timeControls input[type=range] { 
      width:200px;
      height: 6px;
      background: var(--light-border);
      border-radius: 3px;
      outline: none;
      -webkit-appearance: none;
    }
    
    #timeControls input[type=range]::-webkit-slider-thumb {
      -webkit-appearance: none;
      width: 18px;
      height: 18px;
      border-radius: 50%;
      background: var(--secondary-color);
      cursor: pointer;
      transition: all 0.2s ease;
    }
    
    #timeControls input[type=range]::-webkit-slider-thumb:hover {
      transform: scale(1.2);
      box-shadow: 0 0 0 8px rgba(52, 152, 219, 0.1);
    }
    
    #timeLabel { 
      min-width:45px; 
      text-align:center; 
      font-weight:600;
      color: var(--secondary-color);
      font-size: 16px;
    }

    /* 地图占满剩余空间（header 覆盖） */
    #map { 
      position:absolute; 
      top:60px; 
      left:0; 
      right:0; 
      bottom:0; 
      z-index:100;
    }

    /* infoWindow 内容类（供 showDetail 使用） */
    .iw-content { 
      font-size:14px; 
      line-height:1.6; 
      max-width:500px; 
      box-sizing:border-box;
      padding: 15px;
      border-radius: 8px;
      background-color: #fff;
    }
    
    .iw-title { 
      margin:0 0 12px 0; 
      font-size:18px; 
      color:var(--primary-color);
      font-weight: 500;
      padding-bottom: 8px;
      border-bottom: 1px solid var(--light-border);
    }
  </style>

  <script type="text/javascript" src="https://webapi.amap.com/maps?v=2.0&key=522d1dd14b7a3ce646313e52b85282d0"></script>
</head>
<body>
  <header>
    <h1><a href="/" style="color: #fff; text-decoration: none;">智慧历史 · 校园数字地图</a></h1>

    <!-- 左侧搜索 -->
    <div id="searchBox">
      <input id="searchInput" placeholder="按名称搜索地标，按 Enter 或点击搜索"/>
      <button id="searchBtn">🔍</button>
    </div>

    <!-- 中间：地标清单切换与路线菜单 -->
    <div class="center-group">
      <button id="btn-toggleLandmarks" class="btn">地标清单</button>

      <div class="dropdown" id="routeDropdown">
        <button class="drop-toggle">路线菜单 ▼</button>
        <div id="routesMenu" class="dropdown-content" role="menu"></div>
      </div>



    </div>

    <div style="flex:1"></div>
  </header>

  <!-- 时间轴 -->
  <div id="timeControls">
    <input type="range" id="timeSlider" min="1990" max="2024" step="1" value="2021"/>
    <div id="timeLabel">2021</div>
  </div>

  <div id="map"></div>

  <!-- 右侧地标面板 -->
  <div id="landmarkPanel" aria-hidden="true">
    <h3>地标清单</h3>
    <div id="landmarks"></div>
  </div>

  <script>
    let APP = {
      data: null,
      map: null,
      markers: [],
      markerById: new Map(),
      currentYear: 2021,
      polylines: [],
      currentInfoWindow: null
    };

    // 标准化媒体路径，直接使用 JSON 文件中的路径
    function normalizeMedia(path) {
      if (!path) return '';
      // 如果路径以 / 开头，直接返回（已经是绝对路径）
      if (path.startsWith('/')) {
        return path;
      }
      // 否则添加 / 前缀
      return '/' + path;
    }

    async function getData(){
      const r = await fetch('/api/getData');
      return await r.json();
    }

    function initMap(){
      if(APP.map) return;
      APP.map = new AMap.Map('map', {
        center: [114.366792, 30.543333],
        zoom: 16,
        viewMode: '3D',
        pitch: 50
      });
    }

    function updateView(){
      APP.markers.forEach(m => m.setMap(null));
      APP.markers = [];
      APP.markerById.clear();

      const panel = document.getElementById('landmarks');
      panel.innerHTML = '';

      if(!APP.data || !Array.isArray(APP.data.landmarks)) return;

      // 判断是否处于路线模式
      let allowedIds = null;
      if (APP.currentRouteLandmarks && APP.currentRouteLandmarks.length > 0) {
        allowedIds = new Set(APP.currentRouteLandmarks.map((lm) => lm.id));
      }

      APP.data.landmarks.forEach(lm => {
        let lmYear = 9999;
        try { lmYear = parseInt((lm.time||'9999').split('-')[0]); } catch(e){ lmYear = 9999; }

        if(lmYear <= APP.currentYear){
          // 路线过滤（若有路线，只显示属于该路线的地标）
          if(allowedIds && !allowedIds.has(lm.id)) return;

          const marker = new AMap.Marker({ position: [lm.lng, lm.lat], title: lm.name });
          marker.setMap(APP.map);
          APP.markers.push(marker);
          APP.markerById.set(lm.id, marker);

          marker.on('click', () => {
            // 聚焦后再打开详情，减少箭头偏移错位
            APP.map.setCenter([lm.lng, lm.lat]);
            APP.map.setZoom(Math.max(APP.map.getZoom(), 16));
            // 使用新的 showDetail（包含图片预加载）
            showDetail(lm);
          });

          const item = document.createElement('div');
          item.className = 'landmark-item';
          item.innerHTML = `<strong>${escapeHtml(lm.name)}</strong>
            <div style="font-size:12px;color:#666;margin-top:4px">${escapeHtml(lm.summary||'')}</div>
            <div style="font-size:12px;color:#999;margin-top:6px">${escapeHtml(lm.time||'')}</div>`;
          item.onclick = () => {
            APP.map.setCenter([lm.lng, lm.lat]);
            APP.map.setZoom(Math.max(APP.map.getZoom(), 16));
            showDetail(lm);
            try { item.scrollIntoView({behavior:'smooth', block:'center'}); } catch(e){}
          };
          panel.appendChild(item);
        }
      });
    }

    // 新的 showDetail：先聚焦，预加载图片，图片加载完成后再 open InfoWindow
    function showDetail(lm){
      // 关闭已有 infoWindow
      if(APP.currentInfoWindow){
        try{ APP.currentInfoWindow.close(); } catch(e){}
        APP.currentInfoWindow = null;
      }

      const name = escapeHtml(lm.name || '');
      const details = escapeHtml(lm.details || lm.summary || '');
      const time = escapeHtml(lm.time || '');

      // 聚焦地图到该点（先聚焦，避免 infoWindow 在动画中错位）
      try {
        APP.map.setCenter([lm.lng, lm.lat]);
        APP.map.setZoom(Math.max(APP.map.getZoom(), 16));
      } catch(e){}

      // 基础文字内容（不包含图片）
      const baseContentStart = `<div class="iw-content" style="max-width:500px; font-size:14px; line-height:1.4; box-sizing:border-box;">
          <h4 class="iw-title" style="margin:6px 0; font-size:16px; color:#2c3e50;">${name}</h4>
          <p style="margin:4px 0;">${details}</p>
          <p style="margin:4px 0;"><b>时间:</b> ${time}</p>`;

      const baseContentEnd = `</div>`;

      // Helper to open infoWindow with given content (ensures anchor bottom-center)
      function openInfoWithContent(content){
        try {
          const infoWindow = new AMap.InfoWindow({
            content: content,
            anchor: 'bottom-center'
          });
          // 优先使用已有 marker 的位置（如果存在）
          const marker = APP.markerById.get(lm.id);
          if(marker && typeof marker.getPosition === 'function'){
            infoWindow.open(APP.map, marker.getPosition());
          } else {
            infoWindow.open(APP.map, [lm.lng, lm.lat]);
          }
          APP.currentInfoWindow = infoWindow;
        } catch(err){
          console.error('openInfoWithContent error', err);
        }
      }

      if(lm.media && Array.isArray(lm.media) && lm.media.length > 0){
        const raw = lm.media[0];
        const src = normalizeMedia(raw);
        const img = new Image();
        // set crossOrigin if your server supports CORS and you need it; otherwise skip
        img.onload = function(){
          // 当图片已经加载完毕，再生成带图片的内容并打开窗口
          const imgHtml = `<div style="margin:0;padding:0;text-align:center;line-height:0;">
              <img src="${src}" alt="${name}" style="max-width:100%; width:300px; height:auto; border-radius:3px; display:block; margin:0 auto; object-fit:contain;"/>
            </div>`;
          const content = baseContentStart + imgHtml + baseContentEnd;
          openInfoWithContent(content);
        };
        img.onerror = function(){
          // 图片加载失败，降级为无图弹窗
          const content = baseContentStart + baseContentEnd;
          openInfoWithContent(content);
        };
        // 启动加载（这个赋值应该在 onload/onerror 之后以确保事件绑定）
        img.src = src;
        // 另外：为了更快体验，如果图片已经在浏览器缓存，onload 可能会立即被触发
      } else {
        const content = baseContentStart + baseContentEnd;
        openInfoWithContent(content);
      }
    }

    function escapeHtml(s){
      if(!s && s !== 0) return '';
      return String(s).replace(/[&<>"']/g, function(m){
        return {'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[m];
      });
    }

    // 构建路线菜单
    function buildRoutesMenu(){
      const menu = document.getElementById('routesMenu');
      menu.innerHTML = '';
      if(!APP.data || !Array.isArray(APP.data.routes)) return;

      APP.data.routes.forEach((r, i) => {
        const btn = document.createElement('button');
        btn.innerText = r.name || `路线 ${i+1}`;
        btn.onclick = (ev) => {
          ev.stopPropagation(); // 防止冒泡触发 document 点击关闭
          showRoute(i);
          // 点击后可以选择关闭菜单
          closeRouteDropdown();
        };
        menu.appendChild(btn);
      });

      const clearBtn = document.createElement('button');
      clearBtn.innerText = '清除路线';
      clearBtn.style.color = '#fff';
      clearBtn.style.background = '#e74c3c';
      clearBtn.style.padding = '8px 12px';
      clearBtn.style.border = 'none';
      clearBtn.style.cursor = 'pointer';
      clearBtn.style.width = '100%';
      clearBtn.onclick = (ev) => {
        ev.stopPropagation();
        clearRoutes();
        closeRouteDropdown();
      };
      menu.appendChild(clearBtn);
    }

    function showRoute(index){
      clearRoutes();
      if(!APP.data || !Array.isArray(APP.data.routes)) return;

      const r = APP.data.routes[index];
      if(!r || !Array.isArray(r.landmarks)) return;

      APP.currentRouteLandmarks = [];
      APP.currentRouteIndex = 0;

      const points = [];
      r.landmarks.forEach(id => {
        const lm = (APP.data.landmarks||[]).find(x => x.id === id);
        if(lm){
          points.push([lm.lng, lm.lat]);
          APP.currentRouteLandmarks.push(lm);
          const marker = new AMap.Marker({ position:[lm.lng, lm.lat], title: lm.name });
          marker.setMap(APP.map);
          APP.polylines.push(marker); // 存起来以便清除
          marker.on('click', ()=> showDetail(lm));
          // 同时把 marker 存到 markerById（以便 showDetail 使用）
          APP.markerById.set(lm.id, marker);
        }
      });

      if(points.length >= 2){
        const polyline = new AMap.Polyline({
          path: points,
          strokeColor: '#FF4D4F',
          strokeWeight: 4,
          strokeOpacity: 0.85,
          showDir: true
        });
        polyline.setMap(APP.map);
        APP.polylines.push(polyline);
      }

      if(points.length>0){
        APP.map.setCenter(points[0]);
        APP.map.setZoom(16);
      }

      btnNext.style.display = APP.currentRouteLandmarks.length>0 ? 'block' : 'none';

      // 刷新右侧地标清单（仅显示该路线地标）
      updateView();
    }

    function clearRoutes(){
      APP.polylines.forEach(p=>{
        try{ p.setMap(null); }catch(e){}
      });
      APP.polylines = [];
      APP.currentRouteLandmarks = [];
      APP.currentRouteIndex = 0;
      btnNext.style.display = 'none';

      // 恢复显示所有地标
      updateView();
    }

    // 全局新增用于“下一地标点”按钮
    APP.currentRouteLandmarks = [];
    APP.currentRouteIndex = 0;

    // 添加按钮到左上角（保持原位置）
    const btnNext = document.createElement('button');
    btnNext.innerText = '显示下一地标点';
    btnNext.style.position = 'absolute';
    btnNext.style.top = '70px';      // header 下方留点空间
    btnNext.style.left = '20px';
    btnNext.style.zIndex = 2000;
    btnNext.style.padding = '6px 12px';
    btnNext.style.borderRadius = '4px';
    btnNext.style.border = 'none';
    btnNext.style.background = '#3498db';
    btnNext.style.color = '#fff';
    btnNext.style.cursor = 'pointer';
    btnNext.style.display = 'none'; // 初始隐藏
    document.body.appendChild(btnNext);
    btnNext.onclick = function(){
      if(APP.currentRouteLandmarks.length === 0) return;
      const lm = APP.currentRouteLandmarks[APP.currentRouteIndex];
      // 聚焦并显示
      APP.map.setCenter([lm.lng, lm.lat]);
      APP.map.setZoom(Math.max(APP.map.getZoom(), 16));
      showDetail(lm);
      APP.currentRouteIndex = (APP.currentRouteIndex + 1) % APP.currentRouteLandmarks.length;
    };

    // Dropdown open/close helpers (解决 hover 冲突)
    function toggleRouteDropdown(){
      const dd = document.getElementById('routeDropdown');
      if(dd.classList.contains('open')) dd.classList.remove('open');
      else dd.classList.add('open');
    }
    function closeRouteDropdown(){
      const dd = document.getElementById('routeDropdown');
      dd.classList.remove('open');
    }



    // 搜索功能：查找第一个包含关键词的地标并显示
    function searchAndShow(){
      const q = document.getElementById('searchInput').value.trim().toLowerCase();
      if(!q) return;
      if(!APP.data || !Array.isArray(APP.data.landmarks)) return;

      const found = APP.data.landmarks.find(lm => (lm.name||'').toLowerCase().includes(q));
      if(!found){ alert('未找到匹配的地标（按名称模糊匹配）'); return; }
      APP.map.setCenter([found.lng, found.lat]);
      APP.map.setZoom(17);
      showDetail(found);

      // 若右侧面板可见，尝试高亮/滚动到对应项
      const panel = document.getElementById('landmarks');
      const items = panel.querySelectorAll('.landmark-item');
      for(const it of items){
        if(it.innerText && it.innerText.indexOf(found.name) !== -1){
          try { it.scrollIntoView({behavior:'smooth', block:'center'}); } catch(e){}
          const old = it.style.background;
          it.style.background = '#fff3bf';
          setTimeout(()=> it.style.background = old, 1200);
          break;
        }
      }
    }

    async function renderUI(){
      const resp = await getData();
      APP.data = resp.data || resp;
      initMap();
      updateView();
      buildRoutesMenu();
    }

    window.onload = function(){
      // time slider
      const slider = document.getElementById('timeSlider');
      const lbl = document.getElementById('timeLabel');
      slider.addEventListener('input', () => {
        APP.currentYear = parseInt(slider.value, 10) || APP.currentYear;
        lbl.innerText = APP.currentYear;
        updateView();
      });

      // toggle landmark panel
      document.getElementById('btn-toggleLandmarks').onclick = function(){
        const panel = document.getElementById('landmarkPanel');
        panel.style.display = (panel.style.display === 'block') ? 'none' : 'block';
      };

      // dropdown toggle and document click handler to close when clicking outside
      document.querySelector('#routeDropdown .drop-toggle').addEventListener('click', (ev) => {
        ev.stopPropagation();
        toggleRouteDropdown();
      });
      // prevent clicks inside route menu from closing via document click
      document.getElementById('routesMenu').addEventListener('click', (ev) => {
        ev.stopPropagation();
      });



      // close dropdowns when clicking outside
      document.addEventListener('click', () => {
        closeRouteDropdown();
      });

      // search events
      document.getElementById('searchBtn').onclick = searchAndShow;
      document.getElementById('searchInput').addEventListener('keydown', (e) => { if(e.key === 'Enter') searchAndShow(); });

      // load
      renderUI();
    };
  </script>
</body>
</html>
